package com.ftcs.controller;

import cn.hutool.core.date.DateUtil;
import com.ftcs.controller.common.request.InvovedProcessInstanceRequest;
import com.ftcs.controller.common.request.Submit2NextRequest;
import com.ftcs.controller.common.request.TodoTasksRequest;
import com.ftcs.controller.common.service.ActivitiService;
import com.ftcs.entity.LeaveApply;
import com.ftcs.entity.User;
import com.ftcs.entity.User_role;
import com.ftcs.model.*;
import com.ftcs.model.Process;
import com.ftcs.model.historyinstance.LeaveHistoryProcess;
import com.ftcs.service.LeaveService;
import com.ftcs.service.SystemService;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Api(value = "请假流程接口")
@Slf4j
@Controller
public class LeaveController {
    @Autowired
    RepositoryService repositoryService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    FormService formservice;
    @Autowired
    IdentityService identityservice;
    @Autowired
    LeaveService leaveservice;
    @Autowired
    TaskService taskservice;
    @Autowired
    HistoryService histiryservice;
    @Autowired
    SystemService systemservice;
    @Autowired
    private ActivitiService activitiService;


    @PostMapping(value = "/deletedeploy")
    public String deletedeploy(@RequestParam("deployid") String deployid) throws Exception {
        repositoryService.deleteDeployment(deployid, true);
        return "activiti/processlist";
    }

    @GetMapping(value = "/runningprocess")
    public String task() {
        return "activiti/runningprocess";
    }

    @GetMapping(value = "/deptleaderaudit")
    public String mytask() {
        return "activiti/deptleaderaudit";
    }

    @GetMapping(value = "/hraudit")
    public String hr() {
        return "activiti/hraudit";
    }

    @GetMapping(value = "/index")
    public String my() {
        return "index";
    }

    @GetMapping(value = "/leaveapply")
    public String leave() {
        return "activiti/leaveapply";
    }

    @GetMapping(value = "/reportback")
    public String reprotback() {
        return "activiti/reportback";
    }

    @GetMapping(value = "/modifyapply")
    public String modifyapply() {
        return "activiti/modifyapply";
    }


    @GetMapping(value = "/activiti/task-deptleaderaudit")
    String url() {
        return "/activiti/task-deptleaderaudit";
    }

    @GetMapping(value = "/historyprocess")
    public String history() {
        return "activiti/historyprocess";
    }


    @GetMapping(value = "myleaveprocess")
    String myleaveprocess() {
        return "activiti/myleaveprocess";
    }


    @GetMapping(value = "/processlist")
    String process() {
        return "activiti/processlist";
    }


    @GetMapping(value = "myleaves")
    String myleaves() {
        return "activiti/myleaves";
    }

    @PostMapping(value = "/uploadWorkFlowFile")
    public String uploadWorkFlowFile(@RequestParam MultipartFile uploadfile) {
        try {
            String filename = uploadfile.getOriginalFilename();
            InputStream is = uploadfile.getInputStream();
            repositoryService.createDeployment().addInputStream(filename, is).deploy();
        } catch (Exception e) {
            log.error("工作流文件上传失败，文件名：", uploadfile.getOriginalFilename());
        }
        return "index";
    }

    @PostMapping(value = "/getProcessList")
    @ResponseBody
    public PageData<Process> getProcessList(@RequestParam("current") int current,
                                            @RequestParam("rowCount") int pageSize) {
        PageData<Process> grid = new PageData<>(current, pageSize);
        int firstrow = (current - 1) * pageSize;
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().listPage(firstrow, pageSize);
        int total = repositoryService.createProcessDefinitionQuery().list().size();
        List<Process> collect = list.stream().map(processDefinition -> {
            Process process = Process.builder().deploymentId(processDefinition.getDeploymentId())
                    .id(processDefinition.getId()).key(processDefinition.getKey()).name(processDefinition.getName())
                    .resourceName(processDefinition.getResourceName())
                    .diagramResourceName(processDefinition.getDiagramResourceName()).build();
            return process;
        }).collect(Collectors.toList());

        grid.setTotal(total);
        grid.setRows(collect);

        return grid;
    }

    @GetMapping(value = "/showresource")
    public void export(@RequestParam("pdid") String pdid, @RequestParam("resource") String resource,
                       HttpServletResponse response) throws Exception {
        ProcessDefinition def = repositoryService.createProcessDefinitionQuery().processDefinitionId(pdid)
                .singleResult();
        InputStream is = repositoryService.getResourceAsStream(def.getDeploymentId(), resource);
        ServletOutputStream output = response.getOutputStream();
        IOUtils.copy(is, output);
    }

    @PostMapping(value = "/startleave")
    @ResponseBody
    public Msg startleave(LeaveApply apply, HttpSession session) {
        String userid = (String) session.getAttribute("username");
        apply.setUser_id(userid);
        apply.setApply_time(DateUtil.date());
        Map<String, Object> variables = Maps.newHashMap();
        variables.put("applyuserid", userid);
        String processInstanceId = leaveservice.startWorkflow(apply, userid, "leave", variables);
        log.info("流程id" + processInstanceId + "已启动");
        return new Msg("success");
    }

    @ApiOperation("获取部门领导审批代办列表")
    @PostMapping(value = "/getDeptTaskList", produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public PageData<LeaveTask> getDeptTaskList(HttpSession session, @RequestParam("current") int current,
                                               @RequestParam("rowCount") int pageSize) {
        PageData<LeaveTask> grid = new PageData<>(current, pageSize, 0, new ArrayList<>());
        // 先做权限检查，对于没有部门领导审批权限的用户,直接返回空
        String username = (String) session.getAttribute("username");
        User user = systemservice.getUserByUserName(username);
        List<User_role> userroles = user.getUser_roles();
        if (userroles == null) {
            return grid;
        }
        boolean flag = systemservice.validatePerssion(username, "部门领导审批");
        if (flag) {
            TodoTasksRequest request = TodoTasksRequest.builder().current(current).pageSize(pageSize).userGroup("部门经理").build();
            LeaveTaskDTO results = leaveservice.listTodoTasks(request);
            List<LeaveTask> tasks = transTaskList(results.getTaskList());
            grid.setTotal(results.getPageInfo().getTotal());
            grid.setRows(tasks);
        }
        return grid;
    }

    @PostMapping(value = "/hrtasklist", produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public PageData<LeaveTask> hrtasklist(HttpSession session, @RequestParam("current") int current,
                                          @RequestParam("rowCount") int pageSize) {
        PageData<LeaveTask> grid = new PageData<>(current, pageSize, 0, new ArrayList<>());
        // 先做权限检查，对于没有人事权限的用户,直接返回空
        String username = (String) session.getAttribute("username");
        User user = systemservice.getUserByUserName(username);
        List<User_role> userroles = user.getUser_roles();
        if (userroles == null) {
            return grid;
        }
        boolean flag = systemservice.validatePerssion(username, "人事审批");
        // 有权限
        if (flag) {
            TodoTasksRequest request = TodoTasksRequest.builder().current(current).pageSize(pageSize).userGroup("人事").build();
            LeaveTaskDTO results = leaveservice.listTodoTasks(request);
            List<LeaveTask> tasks = transTaskList(results.getTaskList());
            grid.setTotal(results.getPageInfo().getTotal());
            grid.setRows(tasks);

        }
        return grid;
    }

    /**
     * 我的待销假列表
     *
     * @param session
     * @param current
     * @param pageSize
     * @return
     */
    @PostMapping(value = "/xjtasklist", produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public PageData<LeaveTask> getXJtasklist(HttpSession session, @RequestParam("current") int current,
                                             @RequestParam("rowCount") int pageSize) {
        PageData<LeaveTask> grid = new PageData<>(current, pageSize, 0, new ArrayList<>());

        String userid = (String) session.getAttribute("username");
//        List<LeaveApply> results = leaveservice.getPageXJTask(userid, firstrow, pageSize);
        TodoTasksRequest request = TodoTasksRequest.builder().current(current).pageSize(pageSize).userId(userid).taskName("销假").build();
        LeaveTaskDTO results = leaveservice.listTodoTasks(request);
        List<LeaveTask> tasks = transTaskList(results.getTaskList());
        grid.setTotal(results.getPageInfo().getTotal());
        grid.setRows(tasks);
        return grid;
    }

    /**
     * 我的调整任务列表
     *
     * @param session
     * @param current
     * @param pageSize
     * @return
     */
    @PostMapping(value = "/updatetasklist", produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public PageData<LeaveTask> getupdatetasklist(HttpSession session, @RequestParam("current") int current,
                                                 @RequestParam("rowCount") int pageSize) {
        PageData<LeaveTask> grid = new PageData<>(current, pageSize, 0, new ArrayList<>());
        String userid = (String) session.getAttribute("username");
        TodoTasksRequest request = TodoTasksRequest.builder().current(current).pageSize(pageSize).userId(userid).taskName("调整申请").build();
        LeaveTaskDTO results = leaveservice.listTodoTasks(request);
        List<LeaveTask> tasks = transTaskList(results.getTaskList());
        grid.setTotal(results.getPageInfo().getTotal());
        grid.setRows(tasks);
        return grid;
    }

    /**
     * 请假单转换为请假任务详情
     *
     * @param results
     * @return
     */
    private List<LeaveTask> transTaskList(List<LeaveApply> results) {
        return results.stream().map(apply -> {
            LeaveTask task = new LeaveTask();
            task.setApply_time(DateUtil.format(apply.getApply_time(), "yyyy-MM-dd HH:mm:ss"));
            task.setUser_id(apply.getUser_id());
            task.setEnd_time(apply.getEnd_time());
            task.setId(apply.getId());
            task.setLeave_type(apply.getLeave_type());
            task.setProcess_instance_id(apply.getProcess_instance_id());
            task.setProcessdefid(apply.getTask().getProcessDefinitionId());
            task.setReason(apply.getReason());
            task.setStart_time(apply.getStart_time());
            task.setTaskcreatetime(apply.getTask().getCreateTime());
            task.setTaskid(apply.getTask().getId());
            task.setTaskname(apply.getTask().getName());
            return task;
        }).collect(Collectors.toList());
    }


    /**
     * 查看请假详情
     *
     * @param taskId
     * @return
     */
    @PostMapping(value = "/dealtask")
    @ResponseBody
    public LeaveTask dealtask(@RequestParam("taskid") String taskId) {
        String businessKey = activitiService.getBusinessKeyByTaskId(taskId);
        LeaveApply leave = leaveservice.getLeaveApply(new Integer(businessKey));
        LeaveTask leaveTask = new LeaveTask();
        BeanUtils.copyProperties(leave, leaveTask);
        leaveTask.setApply_time(DateUtil.format(leave.getApply_time(), "yyyy-MM-dd HH:mm:ss"));
        return leaveTask;
    }


    @PostMapping(value = "/task/deptcomplete/{taskid}")
    @ResponseBody
    public Msg deptcomplete(HttpSession session, @PathVariable("taskid") String taskid, HttpServletRequest req) {
        String userid = (String) session.getAttribute("username");
        Map<String, Object> variables = Maps.newHashMap();
        String approve = req.getParameter("deptleaderapprove");
        variables.put("deptleaderapprove", approve);

        Submit2NextRequest request = Submit2NextRequest.builder().taskId(taskid).userId(userid).variables(variables).build();
        activitiService.submitTask(request);
        return new Msg("success");
    }

    @PostMapping(value = "/task/hrcomplete/{taskid}")
    @ResponseBody
    public Msg hrcomplete(HttpSession session, @PathVariable("taskid") String taskid, HttpServletRequest req) {
        String userid = (String) session.getAttribute("username");
        Map<String, Object> variables = Maps.newHashMap();
        String approve = req.getParameter("hrapprove");
        variables.put("hrapprove", approve);

        Submit2NextRequest request = Submit2NextRequest.builder().taskId(taskid).userId(userid).variables(variables).build();
        activitiService.submitTask(request);
        return new Msg("success");
    }

    /**
     * 销假完成
     *
     * @param taskid
     * @param req
     * @return
     */
    @PostMapping(value = "/task/reportcomplete/{taskid}")
    @ResponseBody
    public Msg reportbackcomplete(@PathVariable("taskid") String taskid, HttpServletRequest req) {
        String realstart_time = req.getParameter("realstart_time");
        String realend_time = req.getParameter("realend_time");
        leaveservice.completeReportBack(taskid, realstart_time, realend_time);
        return new Msg("success");
    }

    /**
     * 调整申请
     *
     * @param taskid
     * @param leave
     * @param reapply
     * @return
     */
    @PostMapping(value = "/task/updatecomplete/{taskid}")
    @ResponseBody
    public Msg updatecomplete(@PathVariable("taskid") String taskid,
                              @ModelAttribute("leave") LeaveApply leave,
                              @RequestParam("reapply") String reapply) {
        leaveservice.updateComplete(taskid, leave, reapply);
        return new Msg("success");
    }

    /**
     * 参与的正在运行的请假流程
     *
     * @param session
     * @param current
     * @param pageSize
     * @return
     */
    @PostMapping(value = "involvedprocess")
    @ResponseBody
    public PageData<RunningProcess> involvedprocess(HttpSession session, @RequestParam("current") int current,
                                                    @RequestParam("rowCount") int pageSize) {
        int firstrow = (current - 1) * pageSize;
        String userid = (String) session.getAttribute("username");

        int total = (int) runtimeService.createProcessInstanceQuery().processDefinitionKey("leave").involvedUser(userid).count();
        InvovedProcessInstanceRequest request = InvovedProcessInstanceRequest.builder().userId(userid).processDefKey("leave").firstRow(firstrow).pageSize(pageSize).build();
        List<RunningProcess> list = activitiService.listInvolvingProcessInstances(request);

        PageData<RunningProcess> grid = new PageData<>(current, pageSize);
        grid.setTotal(total);
        grid.setRows(list);
        return grid;
    }

    /**
     * 我发起的流程
     *
     * @param session
     * @param current
     * @param pageSize
     * @return
     */
    @PostMapping(value = "myStartupProcess")
    @ResponseBody
    public PageData<RunningProcess> myStartupProcess(HttpSession session, @RequestParam("current") int current,
                                                     @RequestParam("rowCount") int pageSize) {
        PageData<RunningProcess> grid = new PageData<>(current, pageSize);
        int firstrow = (current - 1) * pageSize;
        String userId = (String) session.getAttribute("username");
        log.info("当前用户userId=" + userId);
        //运行时状态下流程实例数量
        int total = (int) runtimeService.createProcessInstanceQuery().processDefinitionKey("leave").involvedUser(userId).count();
        //查询指定条件的流程实例列表
        InvovedProcessInstanceRequest request = InvovedProcessInstanceRequest.builder()
                .userId(userId)
                .processDefKey("leave")
                .firstRow(firstrow).pageSize(pageSize).build();
        List<RunningProcess> list = activitiService.listInvolvingProcessInstances(request);

        List<RunningProcess> resultList = list.stream().filter(process -> {
            LeaveApply leaveApply = leaveservice.getLeaveApply(Integer.parseInt(process.getBusinessKey()));
            return leaveApply.getUser_id().equals(userId);
        }).collect(Collectors.toList());

        grid.setTotal(total);
        grid.setRows(resultList);
        return grid;
    }

    @PostMapping(value = "/getfinishprocess")
    @ResponseBody
    public PageData<LeaveHistoryProcess> getHistory(HttpSession session, @RequestParam("current") int current,
                                                    @RequestParam("rowCount") int pageSize) {
        PageData<LeaveHistoryProcess> grid = new PageData<>(current, pageSize);
        String userid = (String) session.getAttribute("username");
        HistoricProcessInstanceQuery processQuery = histiryservice.createHistoricProcessInstanceQuery().processDefinitionKey("leave").startedBy(userid).finished();
        int total = (int) processQuery.count();
        int firstrow = (current - 1) * pageSize;
        List<HistoricProcessInstance> historyList = processQuery.listPage(firstrow, pageSize);
        List<LeaveHistoryProcess> list = historyList.stream().map(history -> {
            LeaveHistoryProcess his = new LeaveHistoryProcess();
            String bussinesskey = history.getBusinessKey();

            LeaveApply apply = leaveservice.getLeaveApply(Integer.parseInt(bussinesskey));
            his.setLeaveapply(apply);
            his.setBusinessKey(bussinesskey);
            his.setProcessDefinitionId(history.getProcessDefinitionId());
            return his;
        }).collect(Collectors.toList());

        grid.setTotal(total);
        grid.setRows(list);
        return grid;
    }


    @GetMapping(value = "traceprocess/{executionId}")
    public void traceprocess(@PathVariable("executionId") String executionId, HttpServletResponse response)
            throws Exception {
        ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult();
        BpmnModel bpmnmodel = repositoryService.getBpmnModel(process.getProcessDefinitionId());
        List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);
        DefaultProcessDiagramGenerator gen = new DefaultProcessDiagramGenerator();
        // 获得历史活动记录实体（通过启动时间正序排序，不然有的线可以绘制不出来）
        List<HistoricActivityInstance> historicActivityInstances = histiryservice.createHistoricActivityInstanceQuery()
                .executionId(executionId)
                .orderByHistoricActivityInstanceStartTime()
                .asc().list();
        // 计算活动线
        List<String> highLightedFlows = leaveservice.getHighLightedFlows(
                (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(process.getProcessDefinitionId()),
                historicActivityInstances);

        InputStream in = gen.generateDiagram(bpmnmodel, "png", activeActivityIds, highLightedFlows, "宋体", "宋体", null, null, 1.0);
        // InputStream in=gen.generateDiagram(bpmnmodel, "png",
        // activeActivityIds);
        ServletOutputStream output = response.getOutputStream();
        IOUtils.copy(in, output);
    }

    @PostMapping(value = "/processinfo")
    @ResponseBody
    public List<HistoricActivityInstance> processinfo(@RequestParam("instanceid") String instanceid) {
        List<HistoricActivityInstance> his = histiryservice.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceid)
                .orderByHistoricActivityInstanceStartTime()
                .asc().list();
        return his;
    }

}
